#!/bin/bash
# access transmission-cli through openbox menu
# by ondoho/ohnonot 2015-2021

# Depends on:
# - transmission-daemon and transmission-remote
# - xclip for various actions
# - notify-send (optional - the actions are executed regardless, you just don't get a notification)
# - timeout (coreutils)

usage() {
if [ -t 0 ]; then [[ "$*" != "" ]] && echo "$*
"
cat <<EOF
Openbox pipemenu to create a list of recent files with or without icons.

Usage: $0 [options]

Options:
-t int  Set timeout in seconds for transmission-remote commands. Default: $timeout

-x str  Choose different clipboard for copying from & pasting to. Possible
        values: primary, secondary, clipboard. Default: $sel

-g str  Full command to open the (web) UI with options. The URL to connect to
        transmission-remote is inserted whereever you place the string %URL%
        (if required at all). Can also be defined through the TR_GUI environemnt
        variable. No default - if you leave this empty, the according menu
        options won't be displayed.

-u str  URL for transmission-remote. If the environment variable TR_AUTH is
        defined it will be inserted at the right place.
        Default: $url

-T str  Terminal to use for stats. It is possible to append options. 
        Can also be defined through the XTERMINAL environemnt variable.
        Current default: $XTERMINAL

-S      Path or link to a document with information (e.g. about torrent search
        sites). No quality control!
        Default: ${tsearch//"$HOME"/\~}
-b      Browser or document viewer to display the former. Default: $browser
        No quality control!

If any option string contains spaces, enclosing it in quotes might not work due
to how openbox' xml works. Try escaping spaces with a backslash \ instead.

-h      This text.

Internal options (access through the pipemenu):
-l      List all torrents with some minimal stats.
        Clicking/activating each entry will toggle start/pause.
-s      Print out statistics in terminal window

Dependencies:
        bash, transmission-cli/transmission-daemon and timeout (coreutils).
Optional:
        - sed for stats.
        - A notification daemon that provides the notify-send executable
        - one of urxvt or xterm (other terminals not tested).
        - xclip to add torrents from the clipboard.
EOF
else
echo "<openbox_pipe_menu>"
[[ "$*" != "" ]] && echo "<item label=\"$*\"/></openbox_pipe_menu>"
fi
exit 1
}
sepchar="─";sep=''
sel=primary
timeout=3
XTERMINAL="xterm"
action=""
authenv=""
url="http://127.0.0.1:9091"
TR_GUI=""
browser=surf
tsearch="$XDG_CONFIG_HOME/openbox/pipemenus/torrentsearchsites.html"

while getopts "t:x:g:u:T:lshb:S:" opt; do
    case "$opt" in
    t)  [[ "$OPTARG" =~ [0-9]+ ]] && (( OPTARG >= 0 )) && (( OPTARG <= 65535 )) || usage "Option -${opt}: invalid number $OPTARG"
        timeout="$OPTARG"
    ;;
    x)  sel="$OPTARG"
    ;;
    g)  TR_GUI="$OPTARG"
    ;;
    u)  url="$OPTARG"
    ;;
    T)  type "${OPTARG%% *}" >/dev/null || usage "$OPTARG not found in PATH"
        XTERMINAL="$OPTARG"
    ;;
    l)  action=list
    ;;
    s)  action=stats
    ;;
    b)  browser="$OPTARG"
    ;;
    S)  tsearch="$OPTARG"
    ;;
    h)  usage
    ;;
    esac
done

# environment variable TR_AUTH for login to web page
if [[ "$TR_AUTH" == ?*:?* ]]; then
    # if defined, insert into URL:
	url="${url%%:*}://$TR_AUTH@${url#*://}"
	authenv="--authenv"
fi
cmd=( timeout $timeout transmission-remote $authenv )

case "$action" in
    list)   mapfile -t info <<<"$(${cmd[@]} -t all -i | grep -E 'Id: |Name: |State: |Percent Done: |Download Speed: |Upload Speed: ')"
            if [[ "$info" != "" ]]; then
            list=""
            for ((i=0;i<${#info[@]};i+=6)); do
                id="${info[i]#*: }"
                name="${info[$((i+1))]#*: }"
                state="${info[$((i+2))]#*: }"
                case "$state" in
                    Seeding) state=Seed;;
                    Downloading) state=Dnld;;
                    Uploading) state=Upld;;
                    "Up & Down") state=UpDn;;
                    Stopped) state=Stop;;
                    Paused) state=Paus;;
                esac
                perc="${info[$((i+3))]#*: }"
                perc="${perc/.?/}"
                down="${info[$((i+4))]#*: }"
                down="${down/B\/s/}"
                down="${down/ /}"
                down="${down/.??/}"
                up="${info[$((i+5))]#*: }"
                up="${up/B\/s/}"
                up="${up/ /}"
                up="${up/.??/}"
                #~ label="$(printf "%-30s %4s %s ↓%s" "${name:0:30}" "$perc" "$state" "$down↑$up")" # looks good with monospaced font
                label="$(printf "%s %4s ↓%s — %s" "$state" "$perc" "$down↑$up" "${name:0:30}")"
                [[ "$state" == Stop || "$state" == Paus ]] && option="start" || option="stopp"
                list="$list<item label=\"$label\"><action name=\"Execute\"><command><![CDATA[sh -c 'notify-send \"Torrent ${option}ed:\" \"$name\n\$(${cmd[@]} -t $id --${option%p})\"']]></command></action></item>"
            done
            else
            list="<item label=\"Couldn&apos;t get list of torrents.\"/>"
            fi
            echo "<openbox_pipe_menu>${list}</openbox_pipe_menu>"
            exit
    ;;
    stats)  mapfile stats <<<"$(${cmd[@]} -st -si | sed '/^$/d')"
            [[ "$stats" != CURRENT* ]] && stats="COULDN'T GET INFO - TIMEOUT ($timeout}s) REACHED?  "
            members=${#stats[@]}
            longest=0
            for i in "${stats[@]}"; do (( ${#i} > longest )) && longest=${#i}; done
            #~ for ((i=0;i<longest;i++)); do sep="$sep$sepchar"; done
            #~ stats[0]="${stats[0]^^}$sep"
            $XTERMINAL -geometry "$longest"x$((members+1)) -title "Session & statistical info from transmission-daemon" -e bash -c 'echo -n "$@"; read -n1' non "${stats[@]}"
            exit
    ;;
esac

[ -n "$TR_GUI" ] && TR_GUI="${TR_GUI//%URL%/"$url"}"

title=""
ismagnet() {
    [[ "$1" == "magnet:"* ]] || return 1
    title="${1##*dn=}"
    title="${title%%&*}"
    title="$(printf "%b" "${title//%/\\x}")"
}
daemoncount=( $(pidof transmission-daemon) )
count=0
case ${#daemoncount[@]} in
    0)  item[count++]="<item label=\"Start Daemon\">
            <action name=\"Execute\">
                <command>
                    transmission-daemon --log-error
                </command>
            </action>
        </item>"
        [ -n "$TR_GUI" ] && item[count++]="<item label=\"Start Daemon + Open UI\">
            <action name=\"Execute\">
                <command>
                    sh -c 'transmission-daemon --log-error; sleep 2; exec $TR_GUI'
                </command>
            </action>
            </item>"
        ;;
    1)  [ -n "$TR_GUI" ] && item[count++]="<item label=\"Open UI\">
            <action name=\"Execute\">
                <command>
                $TR_GUI
                </command>
            </action>
            </item>"
        type xclip >/dev/null && ismagnet "$(xclip -o -selection $sel)" &&\
            item[count++]="<menu label=\"Add torrent from magnet link (clipboard)\" id=\"addtorrentfromclipboard\">
                <item label=\"Add paused: $title\">
                <action name=\"Execute\">
                    <command>
                    sh -c 'notify-send \"Add paused: $title\" \"\$(${cmd[@]} -a \"\$(xclip -selection $sel -o)\" --start-paused)\"'
                    </command>
                </action>
                </item>
                <item label=\"Add and start: $title\">
                <action name=\"Execute\">
                    <command>
                    sh -c 'notify-send \"Add and start: $title\" \"\$(${cmd[@]} -a \"\$(xclip -selection $sel -o)\" --no-start-paused)\"'
                    </command>
                </action>
                </item>
            </menu>"
        item[count++]="<menu label=\"List all torrents\" execute=\"$0 -l\" id=\"listalltorrents\"/>"
        item[count++]="<item label=\"List transmission-daemon stats in $XTERMINAL\">
        <action name=\"Execute\">
            <command>
            $0 -s
            </command>
        </action>
        </item>"
        item[count++]="<separator/><item label=\"Stop Daemon\">
            <action name=\"Execute\">
                <command>
                    sh -c 'notify-send \"Transmission daemon stopped\" \"\$(${cmd[@]} --exit)\"'
                </command>
            </action>
        </item>"
        ;;
    *)  item[count++]="<separator label=\"Warning, ${#daemoncount[@]} daemons detected!\" />
        <item label=\"Kill all daemons\">
            <action name=\"Execute\">
                <command>
                killall transmission-daemon
                </command>
            </action>
        </item>"
        ;;
esac
# lastly, add a list of torrent search sites
[ -n "$browser" ] && [ -n "$tsearch" ] && item[count]="<separator/><item label=\"Torrent Search Sites\">
    <action name=\"Execute\">
        <command>
            $browser \"$tsearch\"
        </command>
    </action>
</item>"
echo "<openbox_pipe_menu>${item[@]}</openbox_pipe_menu>"
